package com.example.jikeprofiledemo

import android.animation.ObjectAnimator
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import androidx.annotation.IntDef
import androidx.core.animation.doOnEnd
import com.example.jikeprofiledemo.RefreshState.REFRESHING
import com.example.jikeprofiledemo.RefreshState.REVEALING
import com.example.jikeprofiledemo.RefreshState.SETTING
import com.example.jikeprofiledemo.RefreshState.SWITCHING


object RefreshState {
    //显示状态
    const val REVEALING = 0

    //转换状态
    const val SWITCHING = 1 //从 J 变为刷新状态圆环的过程

    //刷新状态
    const val REFRESHING = 2

    //停止刷新过程

    const val SETTING = 3
}

class JikeRefreshIndicator : View {


    @IntDef(value = [REVEALING, SWITCHING, REFRESHING, SETTING])
    annotation class RefreshState


    var radius: Int = 80

    //indicator stroke width
    var indicatorWidth: Int = 20

    var progress: Float = 0.3f

    @RefreshState
    var refreshState = REVEALING

    var paint: Paint

    var indicatorColor: Int

    var indicatorMaskColor: Int

    var arcRect = RectF()

    var startAngle = -360f

    constructor(context: Context) : this(context, null)

    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {

        val typeArray = context.obtainStyledAttributes(attrs, R.styleable.JikeRefreshIndicator)
        radius = typeArray.getDimensionPixelSize(R.styleable.JikeRefreshIndicator_indicator_radius, 80)
        indicatorWidth = typeArray.getDimensionPixelSize(R.styleable.JikeRefreshIndicator_indicator_stroke_width, 20)
        indicatorColor = typeArray.getColor(R.styleable.JikeRefreshIndicator_indicator_color, Color.YELLOW)
        indicatorMaskColor = typeArray.getColor(R.styleable.JikeRefreshIndicator_indicator_undermask_color, Color.BLACK)
        progress = typeArray.getFloat(R.styleable.JikeRefreshIndicator_progress, 0f)
        typeArray.recycle()
        paint = Paint(Paint.ANTI_ALIAS_FLAG)
        paint.style = Paint.Style.STROKE
        paint.color = indicatorColor
        paint.strokeWidth = indicatorWidth.toFloat()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        setMeasuredDimension(radius * 2 + indicatorWidth * 2, radius * 3 + indicatorWidth)
        //init or size changed
        if (arcRect.isEmpty || (arcRect.width() * 2).toInt() != measuredWidth)
            arcRect.set(
                indicatorWidth / 2f,
                measuredHeight - radius * 2f - indicatorWidth / 2f * 3,
                measuredWidth - indicatorWidth / 2f,
                measuredHeight - indicatorWidth / 2f
            )
    }


    override fun onDraw(canvas: Canvas?) {

        when (refreshState) {

            REVEALING -> drawRevealing(canvas)

            SWITCHING -> drawSwitching(canvas)

            REFRESHING -> drawRefreshing(canvas)

            SETTING -> drawSettling(canvas)
        }
    }

    //切换
    private fun drawSwitching(canvas: Canvas?) {
        val sweepAngle = 265f * progress + 90
        canvas?.drawArc(arcRect, -360f, sweepAngle, false, paint)

        val startY = progress * (radius * 2f + indicatorWidth / 2)
        //mask
        canvas?.drawLine(
            measuredWidth - indicatorWidth / 2f,
            startY,
            measuredWidth - indicatorWidth / 2f,
            radius * 2f + indicatorWidth / 2,
            paint
        )

    }

    private fun drawRevealing(canvas: Canvas?) {

        canvas?.save()
        val h = measuredHeight * progress
        canvas?.clipRect(0f, measuredHeight / 2f - h / 2, measuredWidth.toFloat(), measuredHeight / 2f + h / 2)
        canvas?.drawArc(arcRect, -270f, -90f, false, paint)

        val stopY = (1 - progress) * (radius * 2f + indicatorWidth / 2)
        //mask
        paint.color = indicatorMaskColor
        canvas?.drawLine(
            measuredWidth - indicatorWidth / 2f,
            0f,
            measuredWidth - indicatorWidth / 2f,
            stopY,
            paint
        )
        paint.color = indicatorColor
        // line that is in progress
        canvas?.drawLine(
            measuredWidth - indicatorWidth / 2f,
            stopY,
            measuredWidth - indicatorWidth / 2f,
            radius * 2f + indicatorWidth / 2,
            paint
        )

        canvas?.restore()
    }


    private fun drawRefreshing(canvas: Canvas?) {
        startAngle += 10f
        canvas?.drawArc(arcRect, startAngle, 355f, false, paint)
        postInvalidateDelayed(17)
    }


    private fun drawSettling(canvas: Canvas?) {

    }

    fun startRefresh() {
        //从 revealing 状态切换到 switching 状态，switching 状态后开始刷新转圈
        refreshState = SWITCHING
        val valueAnimator = ObjectAnimator.ofFloat(0f, 1f)
            .setDuration(200)
        valueAnimator
            .addUpdateListener {
                updateProgress(it.animatedValue as Float)
            }

        valueAnimator.doOnEnd {
            refreshState = REFRESHING
            postInvalidateOnAnimation()
        }

        valueAnimator.start()
    }

    fun shutRefresh() {
        refreshState = SETTING

        val valueAnimator = ObjectAnimator.ofFloat(0f, 1f)
            .setDuration(200)
        valueAnimator
            .addUpdateListener {
                updateProgress(it.animatedValue as Float)
            }

        valueAnimator.doOnEnd {
            refreshState = REFRESHING
            postInvalidateOnAnimation()
        }

        valueAnimator.start()
    }

    fun updateProgress(progress: Float) {
        this.progress = progress
        postInvalidateOnAnimation()
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
    }

}